This commit is contained in:
18631081161 2025-08-20 16:07:48 +08:00
commit 4240c466d2
13 changed files with 1456 additions and 702 deletions

View File

@ -20,6 +20,7 @@ export const getLocation = async () => {
export const chooseImage = async () => {
return new Promise((resolve, reject) => {
uni.chooseImage({
sourceType:['camera'],
count: 1,
success: (res) => {
resolve(res);
@ -820,7 +821,7 @@ export const saveImageToPhotosAlbum = (image) => {
const link = document.createElement("a");
link.href = image;
// 如果 image 是 blob url 或 http url都可以
link.download = "image_" + Date.now(); // 下载文件名
link.download = "image_" + Date.now()+".jpg"; // 下载文件名
document.body.appendChild(link);
link.click();
document.body.removeChild(link);

View File

@ -2,6 +2,7 @@
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.png">
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))

View File

@ -103,7 +103,8 @@
"mp-weixin" : {
"appid" : "",
"setting" : {
"urlCheck" : false
"urlCheck" : false,
"es6" : true
},
"usingComponents" : true
},

14
node_modules/.package-lock.json generated vendored Normal file
View File

@ -0,0 +1,14 @@
{
"name": "WorkCameraf",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/eruda": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/eruda/-/eruda-3.4.3.tgz",
"integrity": "sha512-J2TsF4dXSspOXev5bJ6mljv0dRrxj21wklrDzbvPmYaEmVoC+2psylyRi70nUPFh1mTQfIBsSusUtAMZtUN+/w==",
"dev": true,
"license": "MIT"
}
}
}

85
node_modules/eruda/README.md generated vendored Normal file
View File

@ -0,0 +1,85 @@
<div align="center">
<a href="https://eruda.liriliri.io/" target="_blank">
<img src="https://eruda.liriliri.io/icon.png" width="400">
</a>
</div>
<h1 align="center">Eruda</h1>
<div align="center">
Console for Mobile Browsers.
[![NPM version][npm-image]][npm-url]
[![Build status][ci-image]][ci-url]
[![Test coverage][codecov-image]][codecov-url]
[![Downloads][jsdelivr-image]][jsdelivr-url]
[![License][license-image]][npm-url]
</div>
[npm-image]: https://img.shields.io/npm/v/eruda?style=flat-square
[npm-url]: https://npmjs.org/package/eruda
[jsdelivr-image]: https://img.shields.io/jsdelivr/npm/hm/eruda?style=flat-square
[jsdelivr-url]: https://www.jsdelivr.com/package/npm/eruda
[ci-image]: https://img.shields.io/github/actions/workflow/status/liriliri/eruda/main.yml?branch=master&style=flat-square
[ci-url]: https://github.com/liriliri/eruda/actions/workflows/main.yml
[codecov-image]: https://img.shields.io/codecov/c/github/liriliri/eruda?style=flat-square
[codecov-url]: https://codecov.io/github/liriliri/eruda?branch=master
[license-image]: https://img.shields.io/npm/l/eruda?style=flat-square
[donate-image]: https://img.shields.io/badge/$-donate-0070ba.svg?style=flat-square
<img src="https://eruda.liriliri.io/screenshot.jpg" style="width:100%">
## Demo
![Demo](https://eruda.liriliri.io/qrcode.png)
Browse it on your phone: [eruda.liriliri.io](https://eruda.liriliri.io/)
## Install
You can get it on npm.
```bash
npm install eruda --save-dev
```
Add this script to your page.
```html
<script src="node_modules/eruda/eruda.js"></script>
<script>eruda.init();</script>
```
It's also available on [jsDelivr](http://www.jsdelivr.com/projects/eruda) and [cdnjs](https://cdnjs.com/libraries/eruda).
```html
<script src="https://cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script>
```
For more detailed usage instructions, please read the documentation at [eruda.liriliri.io](https://eruda.liriliri.io/docs/)!
## Related Projects
* [eruda-android](https://github.com/liriliri/eruda-android): Simple webview with eruda loaded automatically.
* [chii](https://github.com/liriliri/chii): Remote debugging tool.
* [chobitsu](https://github.com/liriliri/chobitsu): Chrome devtools protocol JavaScript implementation.
* [licia](https://github.com/liriliri/licia): Utility library used by eruda.
* [luna](https://github.com/liriliri/luna): UI components used by eruda.
* [vivy](https://github.com/liriliri/vivy-docs): Icon image generation.
## Third Party
* [eruda-pixel](https://github.com/Faithree/eruda-pixel): UI pixel restoration tool.
* [eruda-webpack-plugin](https://github.com/huruji/eruda-webpack-plugin): Eruda webpack plugin.
* [eruda-vue-devtools](https://github.com/Zippowxk/vue-devtools-plugin): Eruda Vue-devtools plugin.
## Backers
<a rel="noreferrer noopener" href="https://opencollective.com/eruda" target="_blank"><img src="https://opencollective.com/eruda/backers.svg?width=890"></a>
## Contribution
Read [Contributing Guide](https://eruda.liriliri.io/docs/contributing.html) for development setup instructions.

1
node_modules/eruda/eruda-polyfill.js generated vendored Normal file

File diff suppressed because one or more lines are too long

536
node_modules/eruda/eruda.d.ts generated vendored Normal file
View File

@ -0,0 +1,536 @@
/**
* Type definitions for Eruda
* @see https://github.com/liriliri/eruda
*/
declare module 'eruda' {
export interface InitDefaults {
/**
* Transparency, 0 to 1
*/
transparency?: number
/**
* Display size, 0 to 100
*/
displaySize?: number
/**
* Theme, defaults to Light or Dark in dark mode
*/
theme?: string
}
export interface InitOptions {
/**
* Container element. If not set, it will append an element directly under html root element
*/
container?: HTMLElement
/**
* Choose which default tools you want, by default all will be added
*/
tool?: string[]
/**
* Auto scale eruda for different viewport settings
*/
autoScale?: boolean
/**
* Use shadow dom for css encapsulation
*/
useShadowDom?: boolean
/**
* Enable inline mode
*/
inline?: boolean
/**
* Default settings
*/
defaults?: InitDefaults
}
export interface Position {
x: number
y: number
}
type AnyFn = (...args: any[]) => any
export interface Emitter {
on(event: string, listener: AnyFn): Emitter
off(event: string, listener: AnyFn): Emitter
once(event: string, listener: AnyFn): Emitter
emit(event: string, ...args: any[]): Emitter
removeAllListeners(event?: string): Emitter
}
/**
* Eruda Plugin
* @see https://eruda.liriliri.io/docs/plugin.html
*/
export interface Tool {
/**
* Every plugin must have a unique name, which will be shown as the tab name on the top.
*/
name: string
/**
* Called when plugin is added, and a document element used to display content is passed in.
* The element is wrapped as a jQuery like object, provided by the licia utility library.
*/
init(el: unknown): void
/**
* Called when switch to the panel. Usually all you need to do is to show the container element.
*/
show(): Tool | undefined
/**
* Called when switch to other panel. You should at least hide the container element here.
*/
hide(): Tool | undefined
/**
* Called when plugin is removed using `eruda.remove('plugin name')`.
*/
destroy(): void
}
export interface ToolConstructor {
new (): Tool
readonly prototype: Tool
extend(tool: Tool): ToolConstructor
}
export interface ConsoleConfig {
/**
* Asynchronous rendering
*/
asyncRender?: boolean
/**
* Enable JavaScript execution
*/
jsExecution?: boolean
/**
* Catch global errors
*/
catchGlobalErr?: boolean
/**
* Override console
*/
overrideConsole?: boolean
/**
* Display extra information
*/
displayExtraInfo?: boolean
/**
* Display unenumerable properties
*/
displayUnenumerable?: boolean
/**
* Access getter value
*/
displayGetterVal?: boolean
/**
* Stringify object when clicked
*/
lazyEvaluation?: boolean
/**
* Auto display if error occurs
*/
displayIfErr?: boolean
/**
* Max log number
*/
maxLogNum?: string
}
export interface Log {
type: string
}
export interface ErudaConsole extends Tool, Console {
config: {
set<K extends keyof ConsoleConfig>(name: K, value: ConsoleConfig[K]): void
}
/**
* Custom filter
*/
filter(pattern: string | RegExp | ((log: Log) => boolean)): void
/**
* Html string
*/
html(htmlStr: string): void
}
export interface ErudaConsoleConstructor {
new (): ErudaConsole
readonly prototype: ErudaConsole
}
export interface ElementsConfig {
/**
* Catch Event Listeners
*/
overrideEventTarget?: boolean
/**
* Auto Refresh
*/
observeElement?: boolean
}
export interface Elements extends Tool {
config: {
set<K extends keyof ElementsConfig>(
name: K,
value: ElementsConfig[K]
): void
}
/**
* Element to display
*/
select(el: HTMLElement): void
}
export interface ElementsConstructor {
new (): Elements
readonly prototype: Elements
}
export interface Network extends Tool {
/**
* Clear requests
*/
clear(): void
/**
* Get request data
*/
requests(): object[]
}
export interface NetworkConstructor {
new (): Network
readonly prototype: Network
}
export interface ResourcesConfig {
/**
* Hide Eruda Setting
*/
hideErudaSetting?: boolean
/**
* Auto Refresh Elements
*/
observeElement?: boolean
}
export interface Resources extends Tool {
config: {
set<K extends keyof ResourcesConfig>(
name: K,
value: ResourcesConfig[K]
): void
}
}
export interface ResourcesConstructor {
new (): Resources
readonly prototype: Resources
}
export interface SourcesConfig {
/**
* Show Line Numbers
*/
showLineNum?: boolean
/**
* Beautify Code
*/
formatCode?: boolean
/**
* Indent Size
*/
indentSize?: string
}
export interface Sources extends Tool {
config: {
set<K extends keyof SourcesConfig>(name: K, value: SourcesConfig[K]): void
}
}
export interface SourcesConstructor {
new (): Sources
readonly prototype: Sources
}
export interface InfoItem {
name: string
val: string
}
export interface Info extends Tool {
/**
* Clear infos
*/
clear(): void
/**
* Add info
*/
add(name: string, content: string | (() => void)): void
/**
* Get info or infos
*/
get(): InfoItem[]
get(name: string): string
/**
* Remove specified info
*/
remove(name: string): void
}
export interface InfoConstructor {
new (): Info
readonly prototype: Info
}
export interface Snippets extends Tool {
/**
* Clear snippets
*/
clear(): void
/**
* Add snippet
* @param name Snippet name
* @param fn Function to be triggered
* @param desc Snippet description
*/
add(name: string, fn: Function, desc: string): void
/**
* Remove specified snippet
* @param name Snippet name
*/
remove(name: string): void
/**
* Run specified snippet
* @param name Snippet name
*/
run(name: string): void
}
export interface SnippetsConstructor {
new (): Snippets
readonly prototype: Snippets
}
export interface SettingsRangeOptions {
min?: number
max?: number
step?: number
}
export interface Settings extends Tool {
/**
* Clear settings
*/
clear(): void
/**
* Remove setting
* @param cfg Config object
* @param name Option name
*/
remove(cfj: object, name: string): void
/**
* Add text
*/
text(str: string): void
/**
* Add switch to toggle a boolean value
* @param cfg Config object created by util.createCfg
* @param name Option name
* @param desc Option description
*/
switch(cfg: object, name: string, desc: string): void
/**
* Add select to select a number of string values
* @param cfg Config object
* @param name Option name
* @param desc Option description
* @param values Array of strings to select
*/
select(cfg: object, name: string, desc: string, values: string[]): void
/**
* Add range to input a number
* @param cfg Config object
* @param name Option name
* @param desc Option description
* @param options Min, max, step
*/
range(
cfg: object,
name: string,
desc: string,
options?: SettingsRangeOptions
): void
/**
* Add a separator
*/
separator(): void
}
export interface SettingsConstructor {
new (): Settings
readonly prototype: Settings
}
export interface EntryBtn extends Emitter {
show(): void
hide(): void
getPos(): Position
setPos(pos: Position): void
destroy(): void
}
export interface EntryBtnConstructor {
new (): EntryBtn
readonly prototype: EntryBtn
}
export interface DevTools extends Emitter {
show(): DevTools
hide(): DevTools
toggle(): void
add(tool: Tool | object): DevTools
remove(name: string): DevTools
removeAll(): DevTools
get<T extends ToolConstructor>(name: string): InstanceType<T> | undefined
showTool(name: string): DevTools
initCfg(settings: Settings): void
notify(content: string, options: object): void
destroy(): void
}
export interface DevToolsConstructor {
new (): DevTools
readonly prototype: DevTools
}
/**
* Eruda Util
* @see https://eruda.liriliri.io/docs/plugin.html#utility
*/
export interface Util {
evalCss(css: string): HTMLStyleElement
isErudaEl(val: any): boolean
isDarkTheme(theme?: string): boolean
getTheme(): string
}
interface IToolNameMap {
console: InstanceType<ErudaConsoleConstructor>
elements: InstanceType<ElementsConstructor>
info: InstanceType<InfoConstructor>
network: InstanceType<NetworkConstructor>
resources: InstanceType<ResourcesConstructor>
settings: InstanceType<SettingsConstructor>
snippets: InstanceType<SnippetsConstructor>
sources: InstanceType<SourcesConstructor>
entryBtn: InstanceType<EntryBtnConstructor>
}
/**
* Eruda APIs
* @see https://eruda.liriliri.io/docs/api.html
*/
export interface ErudaApis {
/**
* Initialize eruda.
*/
init(options?: InitOptions): void
/**
* Destory eruda.
* Note: You can call `init` method again after destruction.
*/
destroy(): void
/**
* Set or get scale.
*/
scale(): number
scale(s: number): Eruda
/**
* Set or get entry button position.
* It will not take effect if given pos is out of range.
*/
position(): Position
position(p: Position): Eruda
/**
* Get tool, eg. console, elements panels.
*/
get<K extends keyof IToolNameMap>(name: K): IToolNameMap[K]
get<T extends ToolConstructor>(name: string): InstanceType<T> | undefined
get(): InstanceType<DevToolsConstructor>
/**
* Add tool.
*/
add<T extends ToolConstructor>(
tool: InstanceType<T> | ((eruda: Eruda) => InstanceType<T>)
): Eruda | undefined
/**
* Remove tool.
*/
remove(name: string): Eruda | undefined
/**
* Show eruda panel.
*/
show(name?: string): Eruda | undefined
/**
* Hide eruda panel.
*/
hide(): Eruda | undefined
}
export interface Eruda extends ErudaApis {
/**
* Display console logs. Implementation detail follows the console api spec.
*/
Console: ErudaConsoleConstructor
/**
* Check dom element status.
*/
Elements: ElementsConstructor
/**
* Display special information, could be used for displaying user info to track user logs.
* By default, page url and browser user agent is shown.
*/
Info: InfoConstructor
/**
* Display requests.
*/
Network: NetworkConstructor
/**
* LocalStorage, sessionStorage, cookies, scripts, styleSheets and images.
*/
Resources: ResourcesConstructor
/**
* Customization for all tools.
*/
Settings: SettingsConstructor
/**
* Allow you to register small functions that can be triggered multiple times.
*/
Snippets: SnippetsConstructor
/**
* View object, html, js, and css.
*/
Sources: SourcesConstructor
/**
* Eruda Tool
*/
Tool: ToolConstructor
/**
* Eruda Util
*/
util: Util
/**
* Eruda version
*/
readonly version: string
}
const eruda: Eruda
export default eruda
}

3
node_modules/eruda/eruda.js generated vendored Normal file

File diff suppressed because one or more lines are too long

1
node_modules/eruda/eruda.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

25
node_modules/eruda/package.json generated vendored Normal file
View File

@ -0,0 +1,25 @@
{
"name": "eruda",
"version": "3.4.3",
"description": "Console for Mobile Browsers",
"main": "eruda.js",
"browserslist": [
"since 2015",
"not dead"
],
"repository": {
"type": "git",
"url": "git+https://github.com/liriliri/eruda.git"
},
"keywords": [
"console",
"mobile",
"debug"
],
"author": "redhoodsu",
"license": "MIT",
"bugs": {
"url": "https://github.com/liriliri/eruda/issues"
},
"homepage": "https://eruda.liriliri.io/"
}

19
package-lock.json generated Normal file
View File

@ -0,0 +1,19 @@
{
"name": "WorkCameraf",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"devDependencies": {
"eruda": "^3.4.3"
}
},
"node_modules/eruda": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/eruda/-/eruda-3.4.3.tgz",
"integrity": "sha512-J2TsF4dXSspOXev5bJ6mljv0dRrxj21wklrDzbvPmYaEmVoC+2psylyRi70nUPFh1mTQfIBsSusUtAMZtUN+/w==",
"dev": true,
"license": "MIT"
}
}
}

5
package.json Normal file
View File

@ -0,0 +1,5 @@
{
"devDependencies": {
"eruda": "^3.4.3"
}
}

View File

@ -13,17 +13,25 @@
<!-- 隐藏的canvas用于水印处理仅App/小程序端使用 -->
<!-- #ifndef H5 -->
<canvas canvas-id="watermarkCanvas" style="
<canvas
canvas-id="watermarkCanvas"
style="
position: fixed;
top: -9999px;
left: -9999px;
width: 2000px;
height: 2000px;
"></canvas>
"
></canvas>
<!-- #endif -->
<!-- 弹窗内容 -->
<uni-popup ref="popup" :is-mask-click="false" type="bottom" border-radius="0 0 0 0">
<uni-popup
ref="popup"
:is-mask-click="false"
type="bottom"
border-radius="0 0 0 0"
>
<view class="container">
<view style="height: 80rpx"></view>
@ -31,11 +39,19 @@
<view class="preview-box">
<text class="preview-title">图片预览</text>
<view class="preview-img">
<image :src="imageSrc" @click="handlePreviewImage" mode="aspectFit" class="img"></image>
<image
:src="imageSrc"
@click="handlePreviewImage"
mode="aspectFit"
class="img"
></image>
</view>
<!-- 图片尺寸和文件大小信息 -->
<view class="size-info" v-if="imageSizeInfo.original.width > 0 && false">
<view
class="size-info"
v-if="imageSizeInfo.original.width > 0 && false"
>
<text class="size-text">
原图尺寸: {{ imageSizeInfo.original.width }} x
{{ imageSizeInfo.original.height }}
@ -55,13 +71,23 @@
<!-- 表单区域 -->
<view class="form-item">
<text class="label">位置</text>
<input v-model="locationInfo" type="text" class="input worker-input" />
<input
v-model="locationInfo"
type="text"
class="input worker-input"
disabled
/>
</view>
<!-- 表单区域 -->
<view class="form-item">
<text class="label">请填写工作内容</text>
<uni-combox :candidates="candidates" :clear-able="true" placeholder="请填写工作内容"
@select="handleComboxSelect" v-model="workContent"></uni-combox>
<uni-combox
:candidates="candidates"
:clear-able="true"
placeholder="请填写工作内容"
@select="handleComboxSelect"
v-model="workContent"
></uni-combox>
</view>
<view class="form-item">
@ -73,11 +99,24 @@
<view class="form-item">
<text class="label">请填写施工人员</text>
<view v-for="(worker, index) in workers" :key="index" class="worker-row">
<input type="text" v-model="workers[index]" class="input worker-input" />
<view
v-for="(worker, index) in workers"
:key="index"
class="worker-row"
>
<input
type="text"
v-model="workers[index]"
class="input worker-input"
/>
<view class="btns">
<button class="btn_f" size="mini" @click="addWorker">+</button>
<button v-if="workers.length > 0" class="btn_f" size="mini" @click="removeWorker(index)">
<button
v-if="workers.length > 0"
class="btn_f"
size="mini"
@click="removeWorker(index)"
>
-
</button>
</view>
@ -99,10 +138,20 @@
<button type="primary" class="btn-cancel" @click="handleRetakeCancel">
清空
</button>
<button type="primary" class="btn-save" @click="handleSaveImage" :disabled="isSubmitting">
<button
type="primary"
class="btn-save"
@click="handleSaveImage"
:disabled="isSubmitting"
>
保存图片
</button>
<button type="primary" class="btn-submit" @click="handleSaveAndSubmit" :disabled="isSubmitting">
<button
type="primary"
class="btn-submit"
@click="handleSaveAndSubmit"
:disabled="isSubmitting"
>
提交数据
</button>
</view>
@ -112,10 +161,9 @@
</template>
<script setup>
import {
ref
} from "vue";
import {
import { ref } from "vue";
// import eruda from "eruda";
import {
getLocation,
chooseImage,
addWatermark,
@ -123,28 +171,24 @@
getCachedLogo,
saveImageToPhotosAlbum,
imageToBase64,
} from "../../common/utils";
import {
} from "../../common/utils";
import {
getLocationTranslate,
getLocationGeocoder,
} from "../../common/mapTranslateResult";
import {
getConfig,
addWatermarkRecord
} from "../../common/server";
import {
onLoad
} from "@dcloudio/uni-app";
} from "../../common/mapTranslateResult";
import { getConfig, addWatermarkRecord } from "../../common/server";
import { onLoad } from "@dcloudio/uni-app";
//
// window.erudaInstance = eruda.init();
// ==================== ====================
//
const title = ref("随工水印相机");
const candidates = ref([]);
const workContent = ref(""); //
const popup = ref(null);
// ==================== ====================
//
const title = ref("水印相机");
const candidates = ref([]);
const workContent = ref(""); //
const popup = ref(null);
//
const locations = ref({
//
const locations = ref({
location: {
lat: null,
lng: null,
@ -154,12 +198,12 @@
lng: null,
locationInfo: null,
},
});
});
//
const imageSrc = ref("");
const originalImageSrc = ref("");
const imageSizeInfo = ref({
//
const imageSrc = ref("");
const originalImageSrc = ref("");
const imageSizeInfo = ref({
original: {
width: 0,
height: 0,
@ -170,34 +214,34 @@
height: 0,
fileSize: null,
},
});
});
//
const departments = ref(["请选择"]);
const deptIndex = ref(0);
const workers = ref([""]);
const statusList = ref([]);
const statusIndex = ref(0);
//
const departments = ref(["请选择"]);
const deptIndex = ref(0);
const workers = ref([""]);
const statusList = ref([]);
const statusIndex = ref(0);
var locationData = new Map();
//
const locationInfo = ref("");
const currentTime = ref("");
const isSubmitting = ref(false); //
let logo = ""; //
//
const locationInfo = ref("");
const currentTime = ref("");
const isSubmitting = ref(false); //
let logo = ""; //
// ==================== ====================
//
const handleStartCapture = async () => {
// ==================== ====================
//
const handleStartCapture = async () => {
uni.showLoading({
title: "加载中。。。",
});
try {
//
const locationData = await getLocation();
console.log("系统坐标", locationData);
const _locationData = await getLocation();
console.log("系统坐标", _locationData);
const location = locationData.latitude + "," + locationData.longitude;
const location = _locationData.latitude + "," + _locationData.longitude;
console.log("经纬度", location);
const translate = await getLocationTranslate(location);
@ -208,8 +252,8 @@
console.log("地理编码结果", geocoderResult);
//
locations.value.location.lat = locationData.latitude;
locations.value.location.lng = locationData.longitude;
locations.value.location.lat = _locationData.latitude;
locations.value.location.lng = _locationData.longitude;
locations.value.translate.lat = translate.lat;
locations.value.translate.lng = translate.lng;
locations.value.translate.locationInfo = geocoderResult || "未知位置";
@ -229,17 +273,17 @@
console.log("错误", error);
uni.hideLoading();
}
};
};
//
const handlePreviewImage = () => {
//
const handlePreviewImage = () => {
uni.previewImage({
urls: [imageSrc.value]
urls: [imageSrc.value],
});
};
};
//
const handleComboxSelect = async (value) => {
//
const handleComboxSelect = async (value) => {
console.log("选择的工作内容:", value);
if (locationData[value] != null) {
var tempData = locationData[value];
@ -262,30 +306,30 @@
await addWatermarkToImage(value);
console.log("加载的历史数据:", tempData);
}
};
};
const handleDeptChange = (e) => {
const handleDeptChange = (e) => {
deptIndex.value = e.detail.value;
};
};
const handleStatusChange = (e) => {
const handleStatusChange = (e) => {
statusIndex.value = e.detail.value;
};
};
//
const addWorker = () => {
//
const addWorker = () => {
workers.value.push("");
};
};
const removeWorker = (index) => {
const removeWorker = (index) => {
if (workers.value.length > 1) {
workers.value.splice(index, 1);
}
};
};
// ==================== ====================
//
const addWatermarkToImage = async (work = "") => {
// ==================== ====================
//
const addWatermarkToImage = async (work = "") => {
try {
const watermarkInfo = {
time: formatDate(currentTime.value),
@ -323,16 +367,16 @@
icon: "error",
});
}
};
};
//
const handleRetakePhoto = () => {
//
const handleRetakePhoto = () => {
popup.value.close();
resetFormData();
};
};
//
const handleSaveImage = async () => {
//
const handleSaveImage = async () => {
//
if (isSubmitting.value) {
return;
@ -376,9 +420,9 @@
isSubmitting.value = false;
}, 1000);
}
};
};
const handleRetakeCancel = async () => {
const handleRetakeCancel = async () => {
workers.value.splice(0, workers.value.length);
workers.value.push("");
statusIndex.value = 0;
@ -386,10 +430,10 @@
workContent.value = "";
loadCandidates();
await addWatermarkToImage();
};
var locationData = {};
//
const handleSaveAndSubmit = async () => {
};
//
const handleSaveAndSubmit = async () => {
//
if (isSubmitting.value) {
return;
@ -409,6 +453,7 @@
//
await addWatermarkToImage();
var saveData = {
workContent: workContent.value,
workers: workers.value.filter((worker) => worker.trim() !== ""),
@ -416,9 +461,12 @@
dept: departments.value[deptIndex.value],
date: new Date().toISOString(), // 使ISO
};
console.log(saveData);
console.log("locationData", locationData);
locationData[workContent.value] = saveData;
uni.setStorageSync("locationData", locationData);
var fromData = {
locations: locations.value,
workContent: workContent.value,
@ -426,8 +474,11 @@
status: statusList.value[statusIndex.value],
dept: departments.value[deptIndex.value],
};
var _remarks = JSON.stringify(locations.value);
var imageBase64 = await imageToBase64(imageSrc.value);
console.log(fromData);
const camRecordWorkDto = {
//
@ -454,6 +505,7 @@
};
var res = await addWatermarkRecord(camRecordWorkDto);
console.log(res);
if (res.code != 200) {
uni.hideLoading();
uni.showToast({
@ -462,18 +514,13 @@
});
return;
}
//
if (imageSrc.value) {
await saveImageToPhotosAlbum(imageSrc.value);
}
uni.hideLoading();
uni.showToast({
title: "保存成功",
title: "提交成功",
icon: "success",
});
handleRetakePhoto();
} catch (error) {
console.error("保存失败:", error);
uni.hideLoading();
@ -487,11 +534,26 @@
isSubmitting.value = false;
}, 1000);
}
};
// ==================== ====================
//
const validateFormData = (isSubmit = false) => {
try {
//
if (imageSrc.value) {
await saveImageToPhotosAlbum(imageSrc.value);
}
} catch (error) {
console.error("保存图片失败", error);
uni.hideLoading();
uni.showToast({
title: "保存图片失败",
icon: "error",
});
}
handleRetakePhoto();
};
// ==================== ====================
//
const validateFormData = (isSubmit = false) => {
// -
if (!locationInfo.value || locationInfo.value.trim() === "") {
uni.showToast({
@ -528,20 +590,20 @@
return false;
}
if (statusIndex.value === 0) {
uni.showToast({
title: "请选择项目状态",
icon: "error",
});
return false;
}
// if (statusIndex.value === 0) {
// uni.showToast({
// title: "",
// icon: "error",
// });
// return false;
// }
}
return true;
};
};
//
const resetFormData = () => {
//
const resetFormData = () => {
imageSrc.value = "";
originalImageSrc.value = "";
locationInfo.value = "";
@ -564,9 +626,9 @@
deptIndex.value = 0;
workContent.value = "";
loadCandidates();
};
};
const loadCandidates = () => {
const loadCandidates = () => {
candidates.value.splice(0, candidates.value.length);
//
@ -583,9 +645,9 @@
console.log(`工作内容: ${key}, 时间: ${data.date}`);
candidates.value.push(key);
});
};
// ==================== ====================
onLoad(async () => {
};
// ==================== ====================
onLoad(async () => {
uni.showLoading({
title: "loading...",
});
@ -602,7 +664,7 @@
await getCachedLogo(logo);
var _locationData = uni.getStorageSync("locationData");
if (_locationData != null) {
if (_locationData != null && _locationData != "") {
locationData = _locationData;
loadCandidates();
}
@ -611,11 +673,11 @@
} finally {
uni.hideLoading();
}
});
});
</script>
<style>
.logo {
.logo {
height: 200px;
width: 200px;
margin: 0 auto;
@ -623,18 +685,18 @@
top: 25%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.btn {
.btn {
width: 100px;
margin: 0 auto;
position: absolute;
bottom: 22%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.title {
.title {
margin: 0 auto;
font-size: 20px;
font-weight: 700;
@ -644,28 +706,28 @@
top: 35%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.container {
.container {
padding: 20rpx;
background: #fff;
height: 100vh;
overflow: auto;
}
}
.preview-box {
.preview-box {
background: #fff;
padding: 20rpx;
margin-bottom: 20rpx;
text-align: center;
}
}
.preview-title {
.preview-title {
font-size: 32rpx;
font-weight: bold;
}
}
.preview-img {
.preview-img {
margin: 20rpx 0;
width: 100%;
height: 400rpx;
@ -674,112 +736,112 @@
justify-content: center;
align-items: center;
text-align: center;
}
}
.img {
.img {
max-width: 100%;
max-height: 400rpx;
}
}
.preview-info {
.preview-info {
font-size: 26rpx;
color: #666;
text-align: left;
margin-top: 10rpx;
}
}
.form-item {
.form-item {
margin-bottom: 20rpx;
}
}
.label {
.label {
font-size: 28rpx;
margin-bottom: 10rpx;
display: block;
}
}
.input {
.input {
border: 1px solid #ddd;
border-radius: 8rpx;
padding: 10rpx;
background: #fff;
}
}
.picker {
.picker {
border: 1px solid #ddd;
border-radius: 8rpx;
padding: 10rpx;
background: #fff;
}
}
.worker-row {
.worker-row {
display: flex;
align-items: center;
margin-bottom: 10rpx;
}
}
.worker-input {
.worker-input {
flex: 1;
}
}
.btns {
.btns {
display: flex;
margin-left: 10rpx;
}
}
.btn_f {
.btn_f {
margin-left: 5rpx;
}
}
.footer {
.footer {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
}
}
.btn-cancel {
.btn-cancel {
background: #007aff;
color: #fff;
}
}
.btn-save {
.btn-save {
background: #28a745;
color: #fff;
}
}
.btn-submit {
.btn-submit {
background: #007aff;
color: #fff;
}
}
.btn-save:disabled,
.btn-submit:disabled {
.btn-save:disabled,
.btn-submit:disabled {
background: #ccc !important;
color: #999 !important;
opacity: 0.6;
}
}
.watermark-btn {
.watermark-btn {
margin-top: 20rpx;
background: #28a745;
color: #fff;
font-size: 28rpx;
padding: 10rpx 30rpx;
border-radius: 8rpx;
}
}
.size-info {
.size-info {
margin-top: 20rpx;
padding: 20rpx;
background: #f8f9fa;
border-radius: 8rpx;
}
}
.size-text {
.size-text {
display: block;
font-size: 24rpx;
color: #666;
margin-bottom: 10rpx;
text-align: center;
}
}
</style>