init
This commit is contained in:
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
/dist
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
31
.replit
Normal file
31
.replit
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
run = "npm run dev"
|
||||||
|
entrypoint = "src/App.jsx"
|
||||||
|
|
||||||
|
hidden = [".config", "tsconfig.json", "tsconfig.node.json", "vite.config.js", ".gitignore"]
|
||||||
|
|
||||||
|
[nix]
|
||||||
|
channel = "stable-22_11"
|
||||||
|
|
||||||
|
[env]
|
||||||
|
PATH = "/home/runner/$REPL_SLUG/.config/npm/node_global/bin:/home/runner/$REPL_SLUG/node_modules/.bin"
|
||||||
|
npm_config_prefix = "/home/runner/$REPL_SLUG/.config/npm/node_global"
|
||||||
|
|
||||||
|
[gitHubImport]
|
||||||
|
requiredFiles = [".replit", "replit.nix", ".config"]
|
||||||
|
|
||||||
|
[packager]
|
||||||
|
language = "nodejs"
|
||||||
|
[packager.features]
|
||||||
|
packageSearch = true
|
||||||
|
guessImports = true
|
||||||
|
enabledForHosting = false
|
||||||
|
|
||||||
|
[languages]
|
||||||
|
[languages.javascript]
|
||||||
|
pattern = "**/{*.js,*.jsx,*.ts,*.tsx}"
|
||||||
|
[languages.javascript.languageServer]
|
||||||
|
start = "typescript-language-server --stdio"
|
||||||
|
|
||||||
|
[deployment]
|
||||||
|
build = ["sh", "-c", "npm run build"]
|
||||||
|
run = ["sh", "-c", "npm run preview"]
|
13
index.html
Normal file
13
index.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Base Script</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
2486
package-lock.json
generated
Normal file
2486
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
package.json
Normal file
32
package.json
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"name": "react-emplate",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"description": "React TypeScript on Replit, using Vite bundler",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc && vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.0.15",
|
||||||
|
"@types/react-dom": "^18.0.6",
|
||||||
|
"@vitejs/plugin-react": "^2.0.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"typescript": "^4.7.4",
|
||||||
|
"vite": "^3.0.4"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@douyinfe/semi-foundation": "^2.38.0",
|
||||||
|
"@douyinfe/semi-ui": "^2.36.0",
|
||||||
|
"@lark-base-open/js-sdk": "^0.3.0",
|
||||||
|
"i18next": "^23.5.1",
|
||||||
|
"i18next-browser-languagedetector": "^7.1.0",
|
||||||
|
"react-i18next": "^13.2.2",
|
||||||
|
"reset-css": "^5.0.1"
|
||||||
|
}
|
||||||
|
}
|
15
public/favicon.svg
Normal file
15
public/favicon.svg
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<svg width="410" height="404" viewBox="0 0 410 404" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M399.641 59.5246L215.643 388.545C211.844 395.338 202.084 395.378 198.228 388.618L10.5817 59.5563C6.38087 52.1896 12.6802 43.2665 21.0281 44.7586L205.223 77.6824C206.398 77.8924 207.601 77.8904 208.776 77.6763L389.119 44.8058C397.439 43.2894 403.768 52.1434 399.641 59.5246Z" fill="url(#paint0_linear)"/>
|
||||||
|
<path d="M292.965 1.5744L156.801 28.2552C154.563 28.6937 152.906 30.5903 152.771 32.8664L144.395 174.33C144.198 177.662 147.258 180.248 150.51 179.498L188.42 170.749C191.967 169.931 195.172 173.055 194.443 176.622L183.18 231.775C182.422 235.487 185.907 238.661 189.532 237.56L212.947 230.446C216.577 229.344 220.065 232.527 219.297 236.242L201.398 322.875C200.278 328.294 207.486 331.249 210.492 326.603L212.5 323.5L323.454 102.072C325.312 98.3645 322.108 94.137 318.036 94.9228L279.014 102.454C275.347 103.161 272.227 99.746 273.262 96.1583L298.731 7.86689C299.767 4.27314 296.636 0.855181 292.965 1.5744Z" fill="url(#paint1_linear)"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear" x1="6.00017" y1="32.9999" x2="235" y2="344" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#41D1FF"/>
|
||||||
|
<stop offset="1" stop-color="#BD34FE"/>
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient id="paint1_linear" x1="194.651" y1="8.81818" x2="236.076" y2="292.989" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#FFEA83"/>
|
||||||
|
<stop offset="0.0833333" stop-color="#FFDD35"/>
|
||||||
|
<stop offset="1" stop-color="#FFA800"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
8
replit.nix
Normal file
8
replit.nix
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{ pkgs }: {
|
||||||
|
deps = [
|
||||||
|
pkgs.nodejs-16_x
|
||||||
|
pkgs.nodePackages.typescript-language-server
|
||||||
|
pkgs.yarn
|
||||||
|
pkgs.replitPackages.jest
|
||||||
|
];
|
||||||
|
}
|
12
src/App.css
Normal file
12
src/App.css
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
@import 'reset-css';
|
||||||
|
|
||||||
|
.main {
|
||||||
|
padding: 1.5rem 1rem 1rem;
|
||||||
|
}
|
||||||
|
.main h4 {
|
||||||
|
font-size: calc(1.275rem + 0.3vw);
|
||||||
|
}
|
||||||
|
.main code {
|
||||||
|
color: #d63384;
|
||||||
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace;
|
||||||
|
}
|
73
src/App.tsx
Normal file
73
src/App.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import './App.css';
|
||||||
|
import { bitable, TableMeta } from "@lark-base-open/js-sdk";
|
||||||
|
import { Button, Form } from '@douyinfe/semi-ui';
|
||||||
|
import { BaseFormApi } from '@douyinfe/semi-foundation/lib/es/form/interface';
|
||||||
|
import { useState, useEffect, useRef, useCallback } from 'react';
|
||||||
|
|
||||||
|
export default function App() {
|
||||||
|
const [tableMetaList, setTableMetaList] = useState<TableMeta[]>();
|
||||||
|
const formApi = useRef<BaseFormApi>();
|
||||||
|
const addRecord = useCallback(async ({ table: tableId }: { table: string }) => {
|
||||||
|
if (tableId) {
|
||||||
|
const table = await bitable.base.getTableById(tableId);
|
||||||
|
table.addRecord({
|
||||||
|
fields: {},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
useEffect(() => {
|
||||||
|
Promise.all([bitable.base.getTableMetaList(), bitable.base.getSelection()])
|
||||||
|
.then(([metaList, selection]) => {
|
||||||
|
setTableMetaList(metaList);
|
||||||
|
formApi.current?.setValues({ table: selection.tableId });
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main className="main">
|
||||||
|
<h4>
|
||||||
|
Edit <code>src/App.tsx</code> and save to reload
|
||||||
|
</h4>
|
||||||
|
<Form labelPosition='top' onSubmit={addRecord} getFormApi={(baseFormApi: BaseFormApi) => formApi.current = baseFormApi}>
|
||||||
|
<Form.Slot label="Development guide">
|
||||||
|
<div>
|
||||||
|
<a href="https://lark-technologies.larksuite.com/docx/HvCbdSzXNowzMmxWgXsuB2Ngs7d" target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
|
Base Extensions Guide
|
||||||
|
</a>
|
||||||
|
、
|
||||||
|
<a href="https://bytedance.feishu.cn/docx/HazFdSHH9ofRGKx8424cwzLlnZc" target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
|
多维表格插件开发指南
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</Form.Slot>
|
||||||
|
<Form.Slot label="API">
|
||||||
|
<div>
|
||||||
|
<a href="https://lark-technologies.larksuite.com/docx/Y6IcdywRXoTYSOxKwWvuLK09sFe" target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
|
Base Extensions Front-end API
|
||||||
|
</a>
|
||||||
|
、
|
||||||
|
<a href="https://bytedance.feishu.cn/docx/HjCEd1sPzoVnxIxF3LrcKnepnUf" target="_blank"
|
||||||
|
rel="noopener noreferrer">
|
||||||
|
多维表格插件API
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</Form.Slot>
|
||||||
|
<Form.Select field='table' label='Select Table' placeholder="Please select a Table" style={{ width: '100%' }}>
|
||||||
|
{
|
||||||
|
Array.isArray(tableMetaList) && tableMetaList.map(({ name, id }) => {
|
||||||
|
return (
|
||||||
|
<Form.Select.Option key={id} value={id}>
|
||||||
|
{name}
|
||||||
|
</Form.Select.Option>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Form.Select>
|
||||||
|
<Button theme='solid' htmlType='submit'>Add Record</Button>
|
||||||
|
</Form>
|
||||||
|
</main>
|
||||||
|
)
|
||||||
|
}
|
37
src/components/LoadApp/index.tsx
Normal file
37
src/components/LoadApp/index.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { ReactElement, useEffect, useState } from "react"
|
||||||
|
import { bitable } from "@lark-base-open/js-sdk"
|
||||||
|
import './style.css'
|
||||||
|
|
||||||
|
export default function LoadApp(props: { neverShowBanner?: boolean, children: ReactElement }): ReactElement {
|
||||||
|
const [loadErr, setLoadErr] = useState(false)
|
||||||
|
|
||||||
|
const TopBanner = <div>
|
||||||
|
<div className='errTop'>
|
||||||
|
After running the project, please get the webview address and paste it into the Base table "Extended Script" for use. See:
|
||||||
|
<a target='_blank' href='https://bytedance.feishu.cn/docx/HazFdSHH9ofRGKx8424cwzLlnZc'>Development Guide</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.neverShowBanner) return;
|
||||||
|
const timer = new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
reject(false)
|
||||||
|
}, 3000)
|
||||||
|
})
|
||||||
|
Promise.race([bitable.bridge.getLanguage(), timer]).then((v) => {
|
||||||
|
setLoadErr(false)
|
||||||
|
}).catch(() => {
|
||||||
|
setLoadErr(true)
|
||||||
|
})
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
if (props.neverShowBanner) {
|
||||||
|
return props.children || null
|
||||||
|
}
|
||||||
|
|
||||||
|
return <div>
|
||||||
|
{loadErr && TopBanner}
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
6
src/components/LoadApp/style.css
Normal file
6
src/components/LoadApp/style.css
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.errTop{
|
||||||
|
padding: 14px;
|
||||||
|
background: #fffbe6;
|
||||||
|
border: 1px solid #ffe58f;
|
||||||
|
border-radius: 8px
|
||||||
|
}
|
8
src/index.tsx
Normal file
8
src/index.tsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import ReactDOM from 'react-dom/client'
|
||||||
|
import './App.css';
|
||||||
|
import App from './App';
|
||||||
|
import LoadApp from './components/LoadApp';
|
||||||
|
// import './locales/i18n' // 支持国际化
|
||||||
|
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<LoadApp ><App /></LoadApp>)
|
||||||
|
|
||||||
|
|
3
src/locales/en.json
Normal file
3
src/locales/en.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"title":"这是英文标题"
|
||||||
|
}
|
34
src/locales/i18n.ts
Normal file
34
src/locales/i18n.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import i18n from 'i18next';
|
||||||
|
import { initReactI18next } from 'react-i18next';
|
||||||
|
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||||
|
import { bitable } from '@lark-base-open/js-sdk';
|
||||||
|
import translationEN from './en.json';
|
||||||
|
import translationZH from './zh.json';
|
||||||
|
|
||||||
|
const resources = {
|
||||||
|
zh: {
|
||||||
|
translation: translationZH,
|
||||||
|
},
|
||||||
|
en: {
|
||||||
|
translation: translationEN,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
i18n
|
||||||
|
.use(LanguageDetector)
|
||||||
|
.use(initReactI18next)
|
||||||
|
.init({
|
||||||
|
resources,
|
||||||
|
fallbackLng: 'en', // 指定降级文案为英文
|
||||||
|
interpolation: {
|
||||||
|
escapeValue: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
bitable.bridge.getLanguage().then((lng) => {
|
||||||
|
if (i18n.language !== lng) {
|
||||||
|
i18n.changeLanguage(lng);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default i18n;
|
3
src/locales/zh.json
Normal file
3
src/locales/zh.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"title":"这是中文标题"
|
||||||
|
}
|
21
tsconfig.json
Normal file
21
tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||||
|
"allowJs": false,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"esModuleInterop": false,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"jsx": "react-jsx"
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
9
tsconfig.node.json
Normal file
9
tsconfig.node.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
11
vite.config.js
Normal file
11
vite.config.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import react from '@vitejs/plugin-react';
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
base: './',
|
||||||
|
plugins: [react()],
|
||||||
|
server: {
|
||||||
|
host: '0.0.0.0',
|
||||||
|
}
|
||||||
|
})
|
Reference in New Issue
Block a user